package com.crm.common.util;

import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.metadata.BaseRowModel;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.metadata.Table;
import com.alibaba.excel.support.ExcelTypeEnum;
import lombok.extern.slf4j.Slf4j;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * @author yuanyunfeng
 * @date 2021/8/24 11:04
 */
@Slf4j
public class EasyExcelUtil {


    private static class ExcelListener extends AnalysisEventListener {
        /**
         * 自定义用于暂时存储data 可以通过实例获取该值
         */
        private List<Object> datas = new ArrayList<>();

        /**
         * 每解析一行都会回调invoke()方法
         *
         * @param object
         * @param context
         */
        @Override
        public void invoke(Object object, AnalysisContext context) {
            // 数据存储到list，供批量处理，或后续自己业务逻辑处理。
            log.debug("解析到第【{}】个sheet页，第【{}】行数据为【{}】", context.getCurrentSheet(), context.getCurrentRowNum(),
                    object.toString());
            datas.add(object);
            // 根据自己业务做处理
        }

        @Override
        public void doAfterAllAnalysed(AnalysisContext context) {
            // 解析结束销毁不用的资源
            // 注意不要调用datas.clear(),否则getDatas为null
        }

    }

    /**
     * 读取Excel
     *
     * @author Tele
     *
     */

    /**
     * 读取excel并插入mysql中 sheet第一个参数为sheetNo代表sheet的编号,第二个参数表示从第几行开始读,最小是1
     *
     * @throws FileNotFoundException
     */
    public static List<Object> readExcel(InputStream inputStream, BaseRowModel baseRowModel)
            throws FileNotFoundException {
        ExcelListener excelListener = new ExcelListener();
        // 解析每行结果在listener中处理
        ExcelReader excelReader = new ExcelReader(inputStream, null, excelListener);
        excelReader.read(new Sheet(1, 1, baseRowModel.getClass()));
        return excelListener.datas;
    }

    /**
     * 读取excel第sheet页数据
     *
     * @param inputStream
     * @param baseRowModel
     * @param sheet
     * @return
     * @throws FileNotFoundException
     */
    public static List<Object> readExcelBysheet(InputStream inputStream, BaseRowModel baseRowModel, int sheet)
            throws FileNotFoundException {
        ExcelListener excelListener = new ExcelListener();
        // 解析每行结果在listener中处理
        // System.out.println("================");
        ExcelReader excelReader = new ExcelReader(inputStream, null, excelListener);
        excelReader.read(new Sheet(sheet, 1, baseRowModel.getClass()));
        return excelListener.datas;
    }

    /**
     * Map<Sheet名，数据模型List>
     *
     * @param result
     */
    public static void writeExcel(Map<String, List<BaseRowModel>> result, OutputStream os) {
        ExcelWriter writer = new ExcelWriter(os, ExcelTypeEnum.XLSX, true);
        Iterator entries = result.entrySet().iterator();
        int sheetNo = 1;
        while (entries.hasNext()) {
            Map.Entry entry = (Map.Entry) entries.next();
            String key = (String) entry.getKey();
            List value = (List) entry.getValue();
            if (!value.isEmpty()) {
                Class modelClass = value.get(0).getClass();
                log.debug("Key = " + key + ", Value = " + value);
                Sheet sheet = new Sheet(sheetNo++, 1, modelClass);
                sheet.setSheetName(key);
                writer.write(value, sheet);
            }
        }
        writer.finish();
        log.info("数据已写出");
    }

    /**
     * @param result  <Sheet名，数据模型List>
     * @param headMap 动态标题
     * @param os
     */
    public static void writeExcelWithMultiHead(Map<String, List<BaseRowModel>> result,
                                               Map<String, List<List<String>>> headMap, OutputStream os) {
        ExcelWriter writer = new ExcelWriter(os, ExcelTypeEnum.XLS, true);
        Iterator entries = result.entrySet().iterator();
        int sheetNo = 1;
        while (entries.hasNext()) {
            Map.Entry entry = (Map.Entry) entries.next();
            String key = (String) entry.getKey();
            List value = (List) entry.getValue();
            if (!value.isEmpty()) {
                Class modelClass = value.get(0).getClass();
                log.debug("Key = " + key + ", Value = " + value);
                Sheet sheet = new Sheet(sheetNo++, 1, modelClass);
                sheet.setSheetName(key);
                Table table = new Table(1);
                table.setHead(headMap.get(key));
                table.setClazz(modelClass);
                writer.write(value, sheet, table);
            }else {
                Sheet sheet = new Sheet(sheetNo++, 1);
                sheet.setSheetName(key);
                Table table = new Table(1);
                table.setHead(headMap.get(key));
                writer.write(value, sheet, table);
            }
        }
        writer.finish();
        log.info("数据已写出");
    }

    public static void writeExcelMax(Map<String, List<BaseRowModel>> result, OutputStream os) {
        ExcelWriter writer = new ExcelWriter(os, ExcelTypeEnum.XLSX, true);
        Iterator entries = result.entrySet().iterator();
        int sheetNo = 1;
        while (entries.hasNext()) {
            Map.Entry entry = (Map.Entry) entries.next();
            String key = (String) entry.getKey();
            List value = (List) entry.getValue();
            if (!value.isEmpty()) {
                Class modelClass = value.get(0).getClass();
                log.debug("Key = " + key + ", Value = " + value);
                Sheet sheet = new Sheet(sheetNo++, 1, modelClass);
                sheet.setSheetName(key);
                writer.write(value, sheet);
            }
        }
        writer.finish();
        log.info("数据已写出");
    }


}
